package com.aionengine.gameserver.services;

import java.util.Iterator;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aionemu.commons.utils.Rnd;
import com.aionemu.commons.services.CronService;
import com.aionengine.gameserver.model.ChatType;
import com.aionengine.gameserver.model.gameobjects.player.Player;
import com.aionengine.gameserver.services.abyss.AbyssPointsService;
import com.aionengine.gameserver.services.teleport.TeleportService2;
import com.aionengine.gameserver.skillengine.SkillEngine;
import com.aionengine.gameserver.skillengine.model.SkillTargetSlot;
import com.aionengine.gameserver.utils.PacketSendUtility;
import com.aionengine.gameserver.world.InstanceType;
import com.aionengine.gameserver.world.World;
import com.aionengine.gameserver.services.item.ItemService;
import com.aionengine.gameserver.world.WorldMap;
import com.aionengine.gameserver.world.WorldMapInstance;
import com.aionengine.gameserver.world.WorldMapInstanceFactory;
import com.aionengine.gameserver.world.WorldMapType;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * @author BlackCore
 */
public class FFAInstance {

    private static final WorldMapType BG_INSTANCE_MAP = WorldMapType.PADMARASHKA_CAVE;
    private static final int BG_INSTANCE_ID = 99;
    private static boolean isAvailable;
    private static final Logger log = LoggerFactory.getLogger(FFAInstance.class);
    public static void start(){
        isAvailable=true;
        sendFFASatus("BG ha iniciado en el sistema.");
    }
    public static void stop(){
        isAvailable = false;
        sendFFASatus("BG ha sido detenido por la fuerza.");
        for (Player p : BGInstance().getPlayersInside()) {
                 TeleportService2.moveToBindLocation(p, true);
        }
    }

    public static void startBgTask() {
        String time = "0 0 0/1 1/1 * ? *";
        CronService.getInstance().schedule(new Runnable() {
            @Override
            public void run() {
                log.info("FFA II Tarea de evento ha iniciado!");
				DateTime now = DateTime.now();
                int hour = now.getHourOfDay();
                if (hour == 15) {
                    isAvailable = true;
                    sendFFASatus(" Campo de batalla disponible, use comando: .bg enter");
                } else {
                    isAvailable = false;
                    for (Player p : BGInstance().getPlayersInside()) {
                    	p.setBGkills(0);
                        TeleportService2.moveToBindLocation(p, true);
                    }
                }
            }
        }, time);
    }

    public synchronized static WorldMapInstance getBGInstance() {
        WorldMap map = World.getInstance().getWorldMap(BG_INSTANCE_MAP.getId());

        log.info("Creating new BGinstance:" + BG_INSTANCE_MAP + " id:" + BG_INSTANCE_ID + " owner:" + 0);
        WorldMapInstance worldMapInstance = WorldMapInstanceFactory.createWorldMapInstance(map, BG_INSTANCE_ID, 0, InstanceType.BG);

        map.addInstance(BG_INSTANCE_ID, worldMapInstance);
        startBgTask();
        //CustomSPAWN.spawnFarmMobsForBG();
        return worldMapInstance;
    }

    public static WorldMapInstance BGInstance() {
        return World.getInstance().getWorldMap(BG_INSTANCE_MAP.getId()).getWorldMapInstanceById(BG_INSTANCE_ID);
    }

    public static boolean isInBG(Player player) {
        return player.getPosition().getWorldMapInstance().isBGInstance();
    }

    public static void onKill(Player killer, Player victim) {
        if (isInBG(killer)) {
            killer.increaseBGkills();
            checkEffect(killer);
        }
    }

    public static void onLogOut(Player player) {
        if (isInBG(player)) {
        	player.setBGkills(0);
        	TeleportService2.moveToBindLocation(player, true);
        }
    }

    public static void onRevive(Player player) {
    	player.setBGkills(0);
    	if(!FFAInstance.isAvailable() == true) {
            TeleportService2.moveToBindLocation(player, true);
            return;
        } else {
        rndTeleport(player);
        player.getKnownList().doUpdate();
        player.getEffectController().removeAbnormalEffectsByTargetSlot(SkillTargetSlot.DEBUFF);
        SkillEngine.getInstance().applyEffectDirectly(19145, player, player, 10000);
        }
    }

    private static int BloodRewardItems [] = {186000236,186000143,182005205,186000137};
    private static void checkEffect(Player killer) {
        int kills = killer.getBGkills();
        switch (kills) {
            case 1:
                broadcastMessage(killer, " Jugador " + killer.getName() + " ha hecho derramar la primera sangre!");
                AbyssPointsService.addAp(killer, 100);
                break;
            case 2:
                broadcastMessage(killer, " Jugador " + killer.getName() + " comete un doble asesinato!");
                AbyssPointsService.addAp(killer, 100);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 3:
                broadcastMessage(killer, " Jugador " + killer.getName() + " comete un triple asesinato!");
                AbyssPointsService.addAp(killer, 150);
                break;
            case 4:
                broadcastMessage(killer, " Jugador " + killer.getName() + " esta de colera!");
                AbyssPointsService.addAp(killer, 150);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 5:
                broadcastMessage(killer, " Jugador " + killer.getName() + " comete una serie de asesinatos!");
                AbyssPointsService.addAp(killer, 200);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 6:
                AbyssPointsService.addAp(killer, 200);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 7:
                AbyssPointsService.addAp(killer, 250);
                break;
            case 8:
                AbyssPointsService.addAp(killer, 250);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 9:
                AbyssPointsService.addAp(killer, 300);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 10:
                broadcastMessage(killer, " Jugador " + killer.getName() + " esta matando a todos!");
                AbyssPointsService.addAp(killer, 300);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 11:
                AbyssPointsService.addAp(killer, 350);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 12:
                AbyssPointsService.addAp(killer, 350);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 13:
                AbyssPointsService.addAp(killer, 400);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 14:
                AbyssPointsService.addAp(killer, 400);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
            case 15:
                broadcastMessage(killer, " Jugador " + killer.getName() + "  se convierte en un asesino en serie! ");
                AbyssPointsService.addAp(killer, 750);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);

                break;

            case 16:
                AbyssPointsService.addAp(killer, 800);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;


            case 17:
                AbyssPointsService.addAp(killer, 850);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 18:
                AbyssPointsService.addAp(killer, 900);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 19:
                AbyssPointsService.addAp(killer, 950);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 20:
                broadcastMessage(killer, " Jugador " + killer.getName() + " esta dominando la zona");
                AbyssPointsService.addAp(killer, 1050);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 21:
                AbyssPointsService.addAp(killer, 1100);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 22:
                AbyssPointsService.addAp(killer, 1150);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 23:
                AbyssPointsService.addAp(killer, 1200);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 24:
                AbyssPointsService.addAp(killer, 1250);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 25:
                broadcastMessage(killer, " Jugador " + killer.getName() + " continua con la masacre!");
                AbyssPointsService.addAp(killer, 1300);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);

                break;

            case 26:
                AbyssPointsService.addAp(killer, 1350);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 27:
                AbyssPointsService.addAp(killer, 1400);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 28:
                AbyssPointsService.addAp(killer, 1450);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 29:
                AbyssPointsService.addAp(killer, 1500);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 30:
                broadcastMessage(killer, " Jugador " + killer.getName() + " esta imparable!");
                AbyssPointsService.addAp(killer, 1550);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 31:
                AbyssPointsService.addAp(killer, 1600);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 32:
                AbyssPointsService.addAp(killer, 1650);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 33:
                AbyssPointsService.addAp(killer, 1700);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 34:
                AbyssPointsService.addAp(killer, 1750);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;

            case 35:
                broadcastMessage(killer, " Jugador " + killer.getName() + "  es un dios! ha asesinado " + kills + " enemigos, su velocidad y fuerza aumentan.");
                switch (killer.getRace()) {
                    case ASMODIANS:
                        SkillEngine.getInstance().applyEffectDirectly(10406, killer, killer, 30000);
                        break;
                    case ELYOS:
                        SkillEngine.getInstance().applyEffectDirectly(10405, killer, killer, 30000);
                        break;

                }
                killer.setBGkills(0);
                AbyssPointsService.addAp(killer, 2000);
                ItemService.addItem(killer, BloodRewardItems[Rnd.get(0, BloodRewardItems.length -1)], 1);
                break;
        }
    }

    public static void onEnterFFA(Player player) {
        if (isInBG(player)) {
            broadcastMessage(player, " Luchador " + player.getName() + " se ha unido al campo de batalla!");
        }
    }

    private static void broadcastMessage(Player killer, final String message) {
        Iterator<Player> iter = killer.getPosition().getWorldMapInstance().playerIterator();
        while (iter.hasNext()) {
            Player player = iter.next();
            PacketSendUtility.sendMessage(player, "BGManager", message, ChatType.GROUP_LEADER);
        }
    }

    public static void rndTeleport(Player player) {
        float[] rnd = floats.get(Rnd.get(0, floats.size() - 1));
        TeleportService2.teleportTo(player, FFAInstance.getBGInstanceMap().getId(), FFAInstance.getBGInstanceId(), rnd[0], rnd[1], rnd[2], (byte) 0);
    	/**if (player.getRace() == Race.ELYOS) {
    		TeleportService2.teleportTo(player, FFAInstance.getBGInstanceMap().getId(), FFAInstance.getBGInstanceId(), 754.25073f, 232.4422f, 1183.8933f, (byte) 0);
    	} else {
    		TeleportService2.teleportTo(player, FFAInstance.getBGInstanceMap().getId(), FFAInstance.getBGInstanceId(), 754.2248f, 1300.9072f, 1183.8933f, (byte) 0);
    	}*/
    }
    private static List<float[]> floats = new ArrayList<float[]>(Arrays.asList(
            new float[]{551.34064f, 132.71556f, 68.99649f},
            new float[]{490.5109f, 201.7301f, 70.57529f},
            new float[]{576.2015f, 306.33914f, 67.69258f},
            new float[]{511.54373f, 438.1517f, 76.087006f},
            new float[]{402.27222f, 356.04465f, 76.12221f},
            new float[]{375.89648f, 516.8887f, 66.00647f}));

    public static void sendFFASatus(String msg) {
        Iterator<Player> iter = World.getInstance().getPlayersIterator();
        while (iter.hasNext()) {
            PacketSendUtility.sendBrightYellowMessageOnCenter(iter.next(), "BGManager:" + msg);
        }
    }

    /**
     * @return the ffaInstanceMap
     */
    public static WorldMapType getBGInstanceMap() {
        return BG_INSTANCE_MAP;
    }

    public static int getBGInstanceId() {
        return BG_INSTANCE_ID;
    }

    public static boolean isAvailable() {
        return isAvailable;
    }
}
